#!/usr/bin/python

import os
import sys
import string
import unicodedata
import codecs

from mutagen.easyid3 import EasyID3
from mutagen.asf import ASF
from mutagen.oggvorbis import OggVorbis

from mutagen.id3 import ID3NoHeaderError

class InvalidFormatException(Exception):
	def __init__(self, value):
		self.value = value
	def __str__(self):
		return repr(self.value)

import unicodedata as ud
all_unicode = ''.join(unichr(i) for i in xrange(65536))
unicode_letters_and_digits = ''.join(c for c in all_unicode if ud.category(c)=='Lu' or ud.category(c)=='Ll' or ud.category(c)=='Nd')

validFilenameChars = "-_.(),&'[] %s" % (unicode_letters_and_digits)

def periodreplace(e):
	if isinstance(e, UnicodeEncodeError):
		result = u''
		for c in e.object:
			result += u'_'
		return (result, e.end)
	else:
		raise e

def slugify(filename):
	cleanedFilename = unicodedata.normalize('NFKD', filename).encode('utf_8', 'periodreplace')
	result = ''
	for c in filename:
		if c in validFilenameChars:
			result += c
		else:
			result += '_'
	return result
		

def dotidy():
	global duplicateerrorcount, missingtagerrorcount, invalidformaterrorcount
	filenames = os.listdir(os.getcwd())
	for filename in filenames:
		if os.path.isdir(filename):
			os.chdir(filename)
			dotidy()
			os.chdir("..")
			if os.listdir(filename) == []:
				os.rmdir(filename)
		else:
			try:
				artist = ""
				album = "Various Albums"
				title = ""

				basename, extension = os.path.splitext(filename)
				extension = extension.lower()

				if extension == ".wma":
					audio = ASF(filename)
					title = slugify(unicode(audio["Title"][0]))
					artist = slugify(unicode(audio["Author"][0]))
					try:
						album = slugify(unicode(audio["WM/AlbumTitle"][0]))
					except KeyError:
						pass

				elif extension == ".mp3": 
					audio = EasyID3(filename)
					title = slugify(audio["title"][0])
					artist = slugify(audio["artist"][0])
					try:
						album = slugify(audio["album"][0])
					except KeyError:
						pass

				elif extension == ".ogg":
					audio = OggVorbis(filename)
					title = slugify(audio["title"][0])
					artist = slugify(audio["artist"][0])
					try:
						album = slugify(audio["album"][0])
					except KeyError:
						pass

				else:
					raise InvalidFormatException(filename)

				mp3directory = os.path.join(root, artist, album)
				mp3path = os.path.join(mp3directory, artist + " - " + title + extension)

				if not os.path.exists(mp3directory):
					os.makedirs(mp3directory)
				if not os.path.exists(mp3path):
					os.rename(filename, mp3path)
				elif not os.path.samefile(filename, mp3path):
					duplicateerrorcount += 1
					if '-v' in sys.argv:
						print 'Duplicate: ' + os.path.abspath(filename)
			except (ID3NoHeaderError, KeyError):
				missingtagerrorcount += 1
				if '-v' in sys.argv:
					print 'Missing tag: ' + os.path.abspath(filename)
			except InvalidFormatException:
				invalidformaterrorcount +=1
				if '-v' in sys.argv:
					print 'Invalid format: ' + os.path.abspath(filename)
	
codecs.register_error('periodreplace', periodreplace)
root = os.getcwd()
duplicateerrorcount = 0
missingtagerrorcount = 0
invalidformaterrorcount = 0
dotidy()
if duplicateerrorcount > 0:
	print `duplicateerrorcount` + " duplicate filename errors."
if missingtagerrorcount > 0:
	print `missingtagerrorcount` + " missing tag errors."
if invalidformaterrorcount > 0:
	print `invalidformaterrorcount` + " invalid format tag errors."
